/*
 * ir.h
 *
 * Edited by: Jeremy Hansen, RANDY Compton
 */


#ifndef IR_H
#define IR_H


#include "symtab.h"

struct tac_t { // Three-address code entry
	enum { // Types of instruction
		TAC_ENTER, TAC_RETURN,
		TAC_SET,
		TAC_EQUAL, TAC_NOTEQ, TAC_LT, TAC_GT, TAC_LEQ, TAC_GEQ,
		TAC_PLUS, TAC_MINUS, TAC_OR,
		TAC_TIMES, TAC_DIV, TAC_MOD, TAC_AND,
		TAC_NEGATE, TAC_NOT,
		TAC_AT, TAC_NEW, TAC_FUNC, TAC_PRINT, TAC_PARAM, TAC_END_FUNC
	} type;
	// Operands
	char *v1;
	char *v2;
	int n2; // The second operand is a numeric constant if v2 is NULL
	char *v3;
	struct tac_t *next;
};

struct ir_t { // Intermediate representation
	char *id;
	struct tac_t *statements;

	char *className;

	struct ir_t *next; // Next source block

	char *cond; // Condition on which to branch
	struct ir_t *child; // Next execution block (also no branch of condition)
	struct ir_t *otherChild; // Yes branch of condition

	struct ir_t *parent; // First parent
	struct ir_t *nextParent; // Next parent at same level

	int numbered; // Has it been value-numbered?
	struct tac_t *stack; // Local value-numbering stack
};

struct ir_list_t { // Hold a list of IRs, one for each function
	struct ir_t *ir;
	struct ir_list_t *next;
};

// Functions
struct ir_t *bbl_new();
void statement_new(struct tac_t **ss, int type, char *v1, char *v2, char *v3);
void const_statement_new(struct tac_t **ss, int type, char *v1, int n2);
struct tac_t *statement_push(struct tac_t *stack, struct tac_t *s);
char *temp_new();

#endif /* IR_H */
